//
//  Swift_CBDTableViewModel.swift
//  SwiftTestDemo
//
//  Created by John on 2018/5/28.
//  Copyright © 2018年 company. All rights reserved.
//

import UIKit

typealias CBDTableViewScrollerViewBlock = (_ scrollView:UIScrollView) -> Void

typealias CBDTableViewScrollerViewZoomingViewBlock = (_ scrollView:UIScrollView) -> (UIView)

typealias CBDTableViewScrollerViewDraggingBlock = (_ scrollView:UIScrollView, _ decelerate:Bool) ->Void

typealias CBDTableViewScrollerViewBeginZoomingBlock = (_ scrollView:UIScrollView, _ view:UIView) -> Void

typealias CBDTableViewScrollerViewDidEndZoomingBlock = (_ scrollView:UIScrollView, _ view:UIView, _ scale:CGFloat) -> Void

typealias CBDTableViewScrollerViewWillEndDraggingBlock = (_ scrollView:UIScrollView, _ view:CGPoint, _ targetContentOffset:UnsafeMutablePointer<CGPoint>) -> Void

class Swift_CBDTableViewModel: NSObject,UITableViewDelegate,UITableViewDataSource {
    
    var sectionModelArray = [Swift_CBDTableViewSectionModel]()
    
    var didScrollBlock:CBDTableViewScrollerViewBlock?
    
    func didScrollBlockAction(block:CBDTableViewScrollerViewBlock?) {
        self.didScrollBlock = block
    }
    
    var didZoomlBlock:CBDTableViewScrollerViewBlock?
    
    func didZoomlBlockAction(block:CBDTableViewScrollerViewBlock?) {
        self.didZoomlBlock = block
    }
    
    var willBeginDraggingBlock:CBDTableViewScrollerViewBlock?
    
    func willBeginDraggingBlockAction(block:CBDTableViewScrollerViewBlock?) {
        self.willBeginDraggingBlock = block
    }
    
    var willEndDraggingBlock:CBDTableViewScrollerViewWillEndDraggingBlock?
    
    func willEndDraggingBlockAction(block:CBDTableViewScrollerViewWillEndDraggingBlock?)  {
        self.willEndDraggingBlock = block
    }
    
    var didEndDraggingBlock:CBDTableViewScrollerViewDraggingBlock?
    
    func didEndDraggingBlockAction(block:CBDTableViewScrollerViewDraggingBlock?) {
        self.didEndDraggingBlock = block
    }
    
    var willBeginDeceleratingBlock:CBDTableViewScrollerViewBlock?
    
    func willBeginDeceleratingBlockAction(block:CBDTableViewScrollerViewBlock?) {
        self.willBeginDeceleratingBlock = block
    }
    
    var didEndDeceleratingBlock:CBDTableViewScrollerViewBlock?
    
    func didEndDeceleratingBlockAction(block:CBDTableViewScrollerViewBlock?) {
        self.didEndDeceleratingBlock = block
    }
    
    var didEndScrollingAnimationBlock:CBDTableViewScrollerViewBlock?
    
    func didEndScrollingAnimationBlockAction(block:CBDTableViewScrollerViewBlock?) {
        self.didEndScrollingAnimationBlock = block
    }
    
    var zoomingViewBlock:CBDTableViewScrollerViewZoomingViewBlock?
    
    func zoomingViewBlockAction(block:CBDTableViewScrollerViewZoomingViewBlock?) {
        self.zoomingViewBlock = block
    }
    
    var willBeginZoomingBlock:CBDTableViewScrollerViewBeginZoomingBlock?
    
    func willBeginZoomingBlockAction(block:CBDTableViewScrollerViewBeginZoomingBlock?) {
        self.willBeginZoomingBlock = block
    }
    
    var didEndZoomingBlock:CBDTableViewScrollerViewDidEndZoomingBlock?
    
    func didEndZoomingBlockAction(block:CBDTableViewScrollerViewDidEndZoomingBlock?) {
        self.didEndZoomingBlock = block
    }
    
    var shouldScrollToTopBlock:CBDTableViewScrollerViewBlock?
    
    func shouldScrollToTopBlockAction(block:CBDTableViewScrollerViewBlock?) {
        self.shouldScrollToTopBlock = block
    }
    
    var didScrollToTopBlock:CBDTableViewScrollerViewBlock?
    
    func didScrollToTopBlockAction(block:CBDTableViewScrollerViewBlock?) {
        self.didScrollToTopBlock = block
    }
    
    enum CBDTableViewModelError:Error {
        case SectionModelError
        case CellModelError
    }
    
    func sectionModelAtSection(section:NSInteger) -> Swift_CBDTableViewSectionModel? {
       let sectionModel:Swift_CBDTableViewSectionModel = self.sectionModelArray[section]
       return sectionModel
    }
    
    func cellModelAtIndexPath(indexPath:IndexPath) -> Swift_CBDTableViewCellModel? {
        let sectionModel:Swift_CBDTableViewSectionModel = self.sectionModelArray[indexPath.section]
        let cellModel:Swift_CBDTableViewCellModel = sectionModel.cellModelArray[indexPath.row]
        return cellModel
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        if cellModel.heightBlock != nil {
            let heightBlock:CBDCellHeightBlock = cellModel.heightBlock!
            return heightBlock(indexPath, tableView)
        }
        else{
            return cellModel.height!
        }
    }
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        let sectionModel:Swift_CBDTableViewSectionModel = self.sectionModelAtSection(section: section)!
        return sectionModel.headerHeight!
    }
    
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        let sectionModel:Swift_CBDTableViewSectionModel = self.sectionModelAtSection(section: section)!
        return sectionModel.footerHeight!
    }
    
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let sectionModel:Swift_CBDTableViewSectionModel = self.sectionModelAtSection(section: section)!
        if sectionModel.headerViewRenderBlock != nil {
            let headerViewRenderBlock1:CBDViewRenderBlock = sectionModel.headerViewRenderBlock!
            return headerViewRenderBlock1(section, tableView)
        }
        else{
            return sectionModel.headerView
        }
    }
    
    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        let sectionModel:Swift_CBDTableViewSectionModel = self.sectionModelAtSection(section: section)!
        if sectionModel.footerViewRenderBlock != nil{
            let footerViewRenderBlock1:CBDViewRenderBlock = sectionModel.footerViewRenderBlock!
            return footerViewRenderBlock1(section, tableView)
        }
        else{
            return sectionModel.footerView
        }
    }
    
    func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        if cellModel.willSelectBlock != nil{
            let willSelectBlock:CBDCellWillSelectBlock = cellModel.willSelectBlock!
            return willSelectBlock(indexPath, tableView)
        }
        return indexPath
    }
    
    func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath? {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        if cellModel.willDeselectBlock != nil{
            let willDeselectBlock:CBDCellWillSelectBlock = cellModel.willDeselectBlock!
            return willDeselectBlock(indexPath, tableView)
        }
        return indexPath
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        if cellModel.selectionBlock != nil{
            let selectionBlock:CBDCellSelectionBlock = cellModel.selectionBlock!
            selectionBlock(indexPath, tableView)
        }
    }
    
    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        if cellModel.deselectionBlock != nil{
            let deselectionBlock:CBDCellSelectionBlock = cellModel.deselectionBlock!
            deselectionBlock(indexPath, tableView)
        }
    }
    
    func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        if cellModel.deleteConfirmationButtonTitle!.length > 0 {
            return cellModel.deleteConfirmationButtonTitle! as String
        }
        return "删除"
    }
    
    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        var array:Array = [UITableViewRowAction]()
        if let editActionsBlock:CBDCellEditActionsBlock = cellModel.editActionsBlock {
            array = editActionsBlock(indexPath,tableView)
        }
        return array
    }
    
    func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        if let beginEditingBlock:CBDCellSelectionBlock = cellModel.beginEditingBlock {
            beginEditingBlock(indexPath, tableView)
        }
    }
    
    func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?) {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath!)!
        if let endEditingBlock:CBDCellSelectionBlock = cellModel.endEditingBlock {
            endEditingBlock(indexPath!, tableView)
        }
    }
    
    //UITableViewDataSource
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return self.sectionModelArray.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let sectionModel:Swift_CBDTableViewSectionModel = self.sectionModelAtSection(section: section)!
        return sectionModel.cellModelArray.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        var cell:UITableViewCell? = nil
        if let renderBlock:CBDCellRenderBlock = cellModel.renderBlock {
            cell = renderBlock(indexPath,tableView)
        }
        return cell!
    }
    
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        if let willDisplayBlock:CBDCellWillDisplayBlock = cellModel.willDisplayBlock {
            willDisplayBlock(cell,indexPath,tableView)
        }
    }
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        let sectionModel:Swift_CBDTableViewSectionModel = self.sectionModelAtSection(section: section)!
        return sectionModel.headerTitle
    }
    
    func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
        let sectionModel:Swift_CBDTableViewSectionModel = self.sectionModelAtSection(section: section)!
        return sectionModel.footerTitle
    }
    
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        return cellModel.canEdit!
    }
    
    func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        return cellModel.editingStyle!
    }
    
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        let cellModel:Swift_CBDTableViewCellModel = self.cellModelAtIndexPath(indexPath: indexPath)!
        if let commitEditBlock:CBDCellCommitEditBlock = cellModel.commitEditBlock {
            commitEditBlock(indexPath,editingStyle,tableView)
        }
    }
    
    //UIScrollViewDelegate
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if (self.didScrollBlock != nil) {
            self.didScrollBlock!(scrollView)
        }
    }
    
    func scrollViewDidZoom(_ scrollView: UIScrollView) {
        if (self.didZoomlBlock != nil) {
            self.didZoomlBlock!(scrollView)
        }
    }
    
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        if (self.willBeginDraggingBlock != nil) {
            self.willBeginDraggingBlock!(scrollView)
        }
    }
    
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        if (self.willEndDraggingBlock != nil) {
            self.willEndDraggingBlock!(scrollView, velocity, targetContentOffset)
        }
    }
    
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        if (self.didEndDraggingBlock != nil) {
            self.didEndDraggingBlock!(scrollView, decelerate)
        }
    }
    
    func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
        if (self.willBeginDeceleratingBlock != nil) {
            self.willBeginDeceleratingBlock!(scrollView)
        }
    }
    
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        if (self.didEndDeceleratingBlock != nil) {
            self.didEndDeceleratingBlock!(scrollView)
        }
    }
    
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        if (self.didEndScrollingAnimationBlock != nil) {
            self.didEndScrollingAnimationBlock!(scrollView)
        }
    }
    
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        if (self.zoomingViewBlock != nil) {
            return self.zoomingViewBlock!(scrollView)
        }
        return nil
    }
    
    func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
        if (self.willBeginZoomingBlock != nil) {
            self.willBeginZoomingBlock!(scrollView, view!)
        }
    }
    
    func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
        if (self.didEndZoomingBlock != nil) {
            self.didEndZoomingBlock!(scrollView, view!, scale)
        }
    }
    
    func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
        if (self.shouldScrollToTopBlock != nil) {
            self.shouldScrollToTopBlock!(scrollView)
        }
        return true
    }
    
    func scrollViewDidScrollToTop(_ scrollView: UIScrollView) {
        if (self.didScrollToTopBlock != nil) {
            self.didScrollToTopBlock!(scrollView)
        }
    }
    
}
